using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;

using Athena.Tools;

using System.Windows.Forms;

namespace Athena
{
    public class ToolManager
    {

        public static int CompareItems(ToolStripItem a, ToolStripItem b)
        {
            return Comparer.Default.Compare(a.Text, b.Text);
        }

        /// <summary>
        /// This function tests, whether a tool with a given Name is available.
        /// </summary>
        /// <param name="sName">The Name of the Tool</param>
        /// <returns>true, if the tool is available, false otherwise.</returns>
        public bool HaveTool(string sName)
        {
            return _oTools.ContainsKey(sName);
        }

        /// <summary>
        /// Returns a tool with a given Name.
        /// </summary>
        /// <param name="sName">Name of the tool</param>
        /// <returns>The requested tool, if the tool could not be found an exception is thrown.</returns>
        public ITool GetTool(string sName)
        {
            if (_oTools.ContainsKey(sName))
            {
                return ((ToolDescription)_oTools[sName]).Tool;
            }
            throw new System.ArgumentException("No such tool.");
        }

        /// <summary>
        /// Returns the Script Engine plugin, if available.
        /// </summary>
        public ScriptingHost ScriptEngine
        {
            get
            {
                ITool oTool = GetTool("Script &Console");
                if (oTool != null && oTool is ScriptingHost)
                {
                    return (ScriptingHost)oTool;
                }
                throw new InvalidOperationException("The script engine is not available at this time.");
            }
        }

        /// <summary>
        /// Returns the default Property Editor
        /// </summary>
        public PropertyControl PropertyEditor
        {
            get
            {
                ITool oTool = GetTool("Property Editor");
                if (oTool != null && oTool is PropertyControl)
                    return (PropertyControl)oTool;
                throw new InvalidOperationException("The property editor is not available at this time.");
            }
        }

        private Plugins.Simulator _SimulationTool = null;
        /// <summary>
        /// the current simulator
        /// </summary>
        public Plugins.Simulator Simulator
        {
            get { return _SimulationTool; }
            set 
            { 
                _SimulationTool = value;
                if (_SimulationTool != null)
                {
                    try
                    {
                        //_SimulationTool.reset();
                        _SimulationTool.CurrentModule = null;
                    }
                    catch (Exception)
                    {
                        Utility.SetMessage("Error loading simulator");
                    }
                }
            }
        }

        private static int _MaxSimulationTime = 1000;
        /// <summary>
        /// Get or set the maximum time allowed for simulation. This prevents simulators
        /// from freezing due to bad simulator or bad model
        /// </summary>
        public static int MaxSimulationTime
        {
            get { return _MaxSimulationTime; }
            set { _MaxSimulationTime = value; }
        }

        private Plugins.Analyzer _AnalyzerTool = null;
        /// <summary>
        /// the current analyzer
        /// </summary>
        public Plugins.Analyzer Analyzer
        {
            get { return _AnalyzerTool; }
            set 
            { 
                _AnalyzerTool = value;
                if (_AnalyzerTool != null)
                {
                    try
                    {
                        _AnalyzerTool.CurrentModule = null;
                    }
                    catch (Exception)
                    {
                        Utility.SetMessage("Error loading analyzer");
                    }
                }
            }
        }

        /// <summary>
        /// open the simulation window
        /// </summary>
        public void StartSimulation()
        {
            ITool simTool = GetTool("Simulation Window");
            if (simTool is Plugins.SimulationControl)
            {
                Plugins.SimulationControl simulationControl = (Plugins.SimulationControl)simTool;
                simulationControl.Show();
            }
        }

        /// <summary>
        /// A list of all the tools that can be categorized as property editors
        /// </summary>
        public List<IGUITool> PropertyEditors = new List<IGUITool>();

        /// <summary>
        /// A list of available simulators
        /// </summary>
        List<ToolDescription> SimulationTools = new List<ToolDescription>();

        public enum Order { FRONT, MIDDLE, BACK }

        class ToolDescription
        {
            private string _sName;

            public string Name
            {
                get { return _sName; }
                set { _sName = value; }
            }
            private string _sDescription;

            public string Description
            {
                get { return _sDescription; }
                set { _sDescription = value; }
            }

            private ITool _oTool;

            public ITool Tool
            {
                get { return _oTool; }
                set { _oTool = value; }
            }
            /// <summary>
            /// Initializes a new instance of the ToolDescription class.
            /// </summary>
            /// <param name="sName"></param>
            /// <param name="sDescription"></param>
            /// <param name="oTool"></param>
            public ToolDescription(string sName, string sDescription, ITool oTool)
            {
                _sName = sName;
                _sDescription = sDescription;
                _oTool = oTool;
            }
            
            public ToolStripItem ToToolStripMenu()
            {
                ToolStripMenuItem oStrip = new ToolStripMenuItem();
                oStrip.Name = _sName;
                oStrip.Text = _sName;
                oStrip.ToolTipText = _sDescription;
                oStrip.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;

                ToolStrip oTempStrip = ToToolStrip();
                if (oTempStrip.Items.Count > 1)
                {
                    ToolStripItem[] oItems = new ToolStripItem[oTempStrip.Items.Count];
                    oTempStrip.Items.CopyTo(oItems, 0);
                    for (int i = 0; i < oItems.Length; i++)
                    {
                        ToolStripItem oTempStripItem = oItems[i];
                        oTempStripItem.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
                        oTempStripItem.TextDirection = ToolStripTextDirection.Horizontal;
                        oTempStripItem.Width = 200;
                    }
                    

                    oStrip.DropDownItems.AddRange(oItems);
                }
                else if (oTempStrip.Items.Count == 0)
                {
                    return null;
                }
                else
                {

                    ToolStripItem oTempStripItem = oTempStrip.Items[0];
                    oTempStripItem.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
                    oTempStripItem.Width = 200;
                    return oTempStripItem;
                }


                return oStrip;
            }
            public ToolStrip ToToolStrip()
            {
                ToolStrip oStrip = new ToolStrip();
                oStrip.Name = _sName;
                oStrip.AllowMerge = true;
                oStrip.AllowItemReorder = true;
                _oTool.SetupToolStrip(oStrip);
                return oStrip;
            }
            internal void RegisterTool(ToolStripContainer oContainer)
            {
                if (oContainer == null) return;
                ToolStrip oStrip = ToToolStrip();
                oContainer.TopToolStripPanel.Controls.Add(oStrip);
            }

            internal void RegisterToolStrip(ToolStrip oToolStrip, bool bInsertSeparator)
            {
                if (bInsertSeparator) oToolStrip.Items.Add("-");
                _oTool.SetupToolStrip(oToolStrip);
            }

            internal void RegisterToolStrip(ToolStrip oToolStrip)
            {
                RegisterToolStrip(oToolStrip, true);
            }

            public override string ToString()
            {

                return _sName + " - " + _sDescription;
            }
        }

        private Hashtable _oTools = new Hashtable();

        public Hashtable Tools
        {
            get { return _oTools; }
        }

        private Hashtable _enabledTools = new Hashtable();
        public Hashtable EnabledTools
        {
            get
            {
                return _enabledTools ;
            }
            set
            {
                _enabledTools = value;
            }
        }

        public List<string> AllToolNames 
        {
            get
            {
                List<string> oResult = new List<string>();
                foreach (ToolDescription toolDesc in _oTools.Values)
                    oResult.Add(toolDesc.Name);
                return oResult;
            }
        }

        private List<Type> _pluginTypes = new List<Type>();

        private ToolManager()
        {
            _pluginTypes = PluginManager.Instance.GetPlugins(typeof(ITool));

            PluginManager.Instance.PluginsChanged += new PluginManager.PluginsChangedDelegate(Instance_PluginsChanged);

            Program.Model.SelectionChanged += new Model.SelectionChangedDelegate(Model_SelectionChanged);
        }

        private ToolStripMenuItem _SelectedMenu;
        public ToolStripMenuItem SelectedMenu
        {
            get { return _SelectedMenu; }
            set { _SelectedMenu = value; }
        }

        void Model_SelectionChanged(object sender, Model.SelectionEventArgs e)
        {
            if (SelectedMenu != null)
            {
                SetupContextMenu(SelectedMenu, Program.Model.SelectedTypes);
            }
        }

        void Instance_PluginsChanged(object sender, EventArgs e)
        {
            _pluginTypes = PluginManager.Instance.GetPlugins(typeof(ITool));

        }
        private static ToolManager _oInstance = new ToolManager();
        public static ToolManager Instance
        {
            get { return _oInstance; }
        }

        /// <summary>
        /// Registers the given simulation tool with the ToolManager
        /// </summary>
        /// <param name="sName">Human readable Name of the Tool</param>
        /// <param name="oTool">Tool Instance</param>
        public void RegisterSimulationTool(string sName, ITool oTool)
        {
            RegisterTool(sName, "", oTool);
            ToolDescription oDesc = _oTools[sName] as ToolDescription;
            foreach (ToolDescription td in SimulationTools)
                if (td.Name == sName) 
                    return;

            if (oDesc != null)
                SimulationTools.Add(oDesc);
        }

        protected static void UncheckAllButtons(ToolStripButton oCurrentButton)
        {
            if (oCurrentButton.Owner != null)
            {
                foreach (object item in oCurrentButton.Owner.Items)
                {
                    if (item is ToolStripButton)
                    {
                        ToolStripButton toolStripButton = (ToolStripButton)item;
                        toolStripButton.Checked = false;
                    }
                }
            }
            oCurrentButton.Checked = true;
        }

        public void SelectSimulationTool(object sender, Plugins.Simulator simulator)
        {
            if (sender is ToolStripButton)
            {
                ToolStripButton item = (ToolStripButton)sender;
                UncheckAllButtons(item);
            }
            Simulator = simulator;
        }

        public void SelectAnalysisTool(object sender, Plugins.Analyzer analyzer)
        {
            Analyzer = analyzer;
        }


        /// <summary>
        /// Registers the given tool with the ToolManager
        /// </summary>
        /// <param name="sName">Human readable Name of the Tool</param>
        /// <param name="oTool">Tool Instance</param>
        public void RegisterTool(string sName, ITool oTool)
        {
            RegisterTool(sName, "", oTool);
        }

        /// <summary>
        /// Registers the given tool with the ToolManager
        /// </summary>
        /// <param name="sName">Human readable Name of the Tool</param>
        /// <param name="sDesctiption">Description of the tool.</param>
        /// <param name="oTool">Tool Instance</param>
        public void RegisterTool(string sName, string sDesctiption, ITool oTool)
        {
            ToolDescription oDesc = new ToolDescription(sName, sDesctiption, oTool);
            if (!_oTools.ContainsKey(sName))
            {
                _oTools.Add(sName, oDesc);

                if (_oToolStripContainer != null && oTool.RequiresNewToolWindow)
                {
                    oDesc.RegisterTool(_oToolStripContainer);
                }
                else if (_oToolStripMenu != null && oTool.HasMenuItems)
                {
                    _oToolStripMenu.Items.Add("-");
                    oTool.SetupToolStrip(_oToolStripMenu);
                }
            }
        }

        public void SetupContextMenu(ToolStripMenuItem oStrip, List<Type> oTypes)
        {
            oStrip.DropDownItems.Clear();
            if (oStrip == null || oTypes == null || oTypes.Count == 0) return;
            oStrip.DropDownItems.AddRange(Utility.GetDrawPanel().DefaultContextMenuItems);

            List<ToolDescription> toolsFront = new List<ToolDescription>(),
                                  toolsMiddle = new List<ToolDescription>(),
                                  toolsBack = new List<ToolDescription>();

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                switch (toolDesc.Tool.Order)
                {
                    case Order.FRONT:
                        toolsFront.Add(toolDesc);
                        break;
                    case Order.MIDDLE:
                        toolsMiddle.Add(toolDesc);
                        break;
                    default:
                        toolsBack.Add(toolDesc);
                        break;
                }
            }

            toolsFront.AddRange(toolsMiddle);
            toolsFront.AddRange(toolsBack);

            foreach (ToolDescription toolDesc in toolsFront)
            {
                ITool tool = toolDesc.Tool;
                if (toolDesc.Tool.HasContextMenuItems && tool.Handles(oTypes))
                {
                    oStrip.DropDownItems.Add("-");
                    ToolStripMenuItem oMenu = new ToolStripMenuItem(toolDesc.Name);
                    oMenu.ToolTipText = toolDesc.Description;
                    toolDesc.Tool.SetupContextMenu(oMenu);
                    oStrip.DropDownItems.Add(oMenu);
                }
            }
        }

        public void SetupContextMenu(ContextMenuStrip oStrip, List<Type> oTypes)
        {
            if (oStrip == null || oTypes == null || oTypes.Count == 0) return;

            List<ToolDescription> toolsFront = new List<ToolDescription>(),
                                  toolsMiddle = new List<ToolDescription>(),
                                  toolsBack = new List<ToolDescription>();

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                switch (toolDesc.Tool.Order)
                {
                    case Order.FRONT:
                        toolsFront.Add(toolDesc);
                        break;
                    case Order.MIDDLE:
                        toolsMiddle.Add(toolDesc);
                        break;
                    default:
                        toolsBack.Add(toolDesc);
                        break;
                }
            }

            toolsFront.AddRange(toolsMiddle);
            toolsFront.AddRange(toolsBack);

            foreach (ToolDescription toolDesc in toolsFront)
            {
                ITool tool = toolDesc.Tool;
                if (toolDesc.Tool.HasContextMenuItems && tool.Handles(oTypes))
                {
                    oStrip.Items.Add("-");
                    ToolStripMenuItem oMenu = new ToolStripMenuItem(toolDesc.Name);
                    oMenu.ToolTipText = toolDesc.Description;
                    toolDesc.Tool.SetupContextMenu(oMenu);
                    oStrip.Items.Add(oMenu);
                }
            }
        }


        public void SetupDockPanel(WeifenLuo.WinFormsUI.Docking.DockPanel oPanel)
        {
            if (oPanel == null) return;

            List<ToolDescription> toolsFront = new List<ToolDescription>(),
                                  toolsMiddle = new List<ToolDescription>(),
                                  toolsBack = new List<ToolDescription>();

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                switch (toolDesc.Tool.Order)
                {
                    case Order.FRONT:
                        toolsFront.Add(toolDesc);
                        break;
                    case Order.MIDDLE:
                        toolsMiddle.Add(toolDesc);
                        break;
                    default:
                        toolsBack.Add(toolDesc);
                        break;
                }
            }

            toolsFront.AddRange(toolsMiddle);
            toolsFront.AddRange(toolsBack);

            foreach (ToolDescription toolDesc in toolsFront)
            {
                if (!Utility.IsType(typeof(IGUITool), toolDesc.Tool.GetType())) continue;
                IGUITool tool = (IGUITool)toolDesc.Tool;
                tool.SetupDockPanel(oPanel);
            }

        }

        /// <summary>
        /// The tools that are displayed to the side
        /// </summary>
        /// <param name="oToolStrip"></param>
        public void SetupToolStrip(ToolStrip oToolStrip)
        {
            if (oToolStrip == null) return;
            List<ToolDescription> oTemp = new List<ToolDescription>();

            List<ToolDescription> toolsFront = new List<ToolDescription>(),
                                  toolsMiddle = new List<ToolDescription>(),
                                  toolsBack = new List<ToolDescription>();

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                switch (toolDesc.Tool.Order)
                {
                    case Order.FRONT:
                        toolsFront.Add(toolDesc);
                        break;
                    case Order.MIDDLE:
                        toolsMiddle.Add(toolDesc);
                        break;
                    default:
                        toolsBack.Add(toolDesc);
                        break;
                }
            }

            toolsBack.AddRange(toolsMiddle);
            toolsBack.AddRange(toolsFront);

            foreach (ToolDescription tool in toolsBack)
            {
                oTemp.Add(tool);
            }
            for (int i = oTemp.Count - 1; i >= 0; i--)
            {
                ToolDescription tool = oTemp[i];
                if (tool.Tool.HasMenuItems && !tool.Tool.RequiresNewToolWindow)
                    tool.RegisterToolStrip(oToolStrip);
            }
        }

        public void SetupSimulatorMenu(ToolStripMenuItem oMenuItem)
        {
            oMenuItem.DropDownItems.Clear();
            foreach (ToolDescription tool in SimulationTools)
            {
                if (EnabledTools[tool.Name] == null || !((bool)(EnabledTools[tool.Name])))
                    continue;

                ToolStripItem oToolMenu = tool.ToToolStripMenu();
                if (oToolMenu == null) continue;
                oMenuItem.DropDownItems.Add(oToolMenu);

            }
        }

        public void SetupPluginsMenu(ToolStripMenuItem oMenuItem)
        {
            oMenuItem.DropDownItems.Clear();

            List<ToolDescription> tools = new List<ToolDescription>();

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (EnabledTools[toolDesc.Name] == null || !((bool)(EnabledTools[toolDesc.Name])))
                    continue;

                if (!SimulationTools.Contains(toolDesc) && !tools.Contains(toolDesc))
                        tools.Add(toolDesc);
            }

            foreach (ToolDescription tool in tools)
            {
                if (EnabledTools[tool.Name] == null || !((bool)(EnabledTools[tool.Name])))
                    continue;

                ToolStripItem oToolMenu = tool.ToToolStripMenu();
                if (oToolMenu == null) continue;
                oMenuItem.DropDownItems.Add(oToolMenu);
            }

            ToolStripItem[] oItems = new ToolStripItem[oMenuItem.DropDownItems.Count];
            oMenuItem.DropDownItems.CopyTo(oItems, 0);
            Array.Sort<ToolStripItem>(oItems, CompareItems);
            oMenuItem.DropDownItems.Clear();
            oMenuItem.DropDownItems.AddRange(oItems);
        }
        public void SetupToolStripContainer(ToolStripContainer oToolStripContainer)
        {
            if (oToolStripContainer == null) return;


            ToolStrip oToolStrip = new ToolStrip();
            oToolStrip.Name = "Plugins";
            oToolStrip.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;

            bool bIsFirst = false;

            List<ToolDescription> toolsFront = new List<ToolDescription>(),
                                  toolsMiddle = new List<ToolDescription>(),
                                  toolsBack = new List<ToolDescription>();

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (EnabledTools[toolDesc.Name] == null || !((bool)(EnabledTools[toolDesc.Name])))
                    continue;

                switch (toolDesc.Tool.Order)
                {
                    case Order.FRONT:
                        toolsFront.Add(toolDesc);
                        break;
                    case Order.MIDDLE:
                        toolsMiddle.Add(toolDesc);
                        break;
                    default:
                        toolsBack.Add(toolDesc);
                        break;
                }
            }

            toolsFront.AddRange(toolsMiddle);
            toolsFront.AddRange(toolsBack);

            foreach (ToolDescription tool in toolsFront)
            {
                if (EnabledTools[tool.Name] == null || !((bool)(EnabledTools[tool.Name])))
                    continue;

                if (tool.Tool.RequiresNewToolWindow)
                {
                    tool.RegisterToolStrip(oToolStrip, bIsFirst);
                    bIsFirst = true;
                }

            }

            oToolStripContainer.TopToolStripPanel.Controls.Add(oToolStrip);

            Control[] oTemp = new Control[oToolStripContainer.TopToolStripPanel.Controls.Count];

            for (int i = 0; i < oToolStripContainer.TopToolStripPanel.Controls.Count; i++)
            {
                oTemp[i] = oToolStripContainer.TopToolStripPanel.Controls[oToolStripContainer.TopToolStripPanel.Controls.Count - 1 - i];
            }
            oToolStripContainer.TopToolStripPanel.Controls.Clear();
            for (int i = 0; i < oTemp.Length; i++)
                oToolStripContainer.TopToolStripPanel.Controls.Add(oTemp[i]);

        }
        public void OnItemDoubleClick(HandledMouseEventArgs args)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (Utility.IsType(typeof(IGUITool), toolDesc.Tool.GetType()))
                {
                    try
                    {
                        IGUITool tool = (IGUITool)toolDesc.Tool;
                        tool.OnItemDoubleClick(args);
                        if (args.Handled) return;
                    }
                    catch (Exception)
                    {

                    }
                }
            }
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType()))
                {

                    try
                    {
                        INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                        tool.OnItemDoubleClick(args);
                        if (args.Handled) return;
                    }
                    catch (Exception)
                    {

                    }
                }
                

            }
        }
        public void OnMouseUp(HandledMouseEventArgs args)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    if (!Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType())) continue;
                    INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                    tool.OnMouseUp(args);
                    if (args.Handled) return;
                }
                catch (Exception)
                {

                }
            }
        }
        public void OnMouseDown(HandledMouseEventArgs args)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {

                try
                {
                    if (!Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType())) continue;
                    INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                    tool.OnMouseDown(args);
                    if (args.Handled) return;
                }
                catch (Exception)
                {

                }
            }
        }
        public void OnMouseMove(HandledMouseEventArgs args)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    if (!Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType())) continue;
                    INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                    tool.OnMouseMove(args);
                    if (args.Handled) return;
                }
                catch (Exception)
                {

                }
            }
        }

        public void OnKeyUp(KeyEventArgs args)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    if (!Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType())) continue;
                    INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                    tool.OnKeyUp(args);
                }
                catch (Exception)
                {

                }
            }
        }
        public void OnKeyDown(KeyEventArgs args)
        {
            if (args.KeyCode == Keys.Space || args.KeyCode == Keys.Escape)
            {
                //DeactivateTools();
                foreach (ToolDescription toolDesc in _oTools.Values)
                {
                    try
                    {
                        if (!(toolDesc.Tool is INonVisualTool)) continue;
                        INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                        if (tool.IsActive) tool.KeepDeactive();
                        Utility.MouseImage = null;
                    }
                    catch (Exception)
                    {

                    }

                }
            }

            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    //if (!Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType())) continue;
                    //INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                    //tool.OnKeyDown(args);
                    toolDesc.Tool.OnKeyDown(args);
                }
                catch (Exception)
                {

                }
            }

        }

        public void OnSelectionChanged()
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    if (!Utility.IsType(typeof(INonVisualTool), toolDesc.Tool.GetType())) continue;
                    INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                    tool.OnSelectionChanged();
                }
                catch (Exception)
                {

                }
            }
        }

        public void PreRender(System.Drawing.Graphics g)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    if (!Utility.IsType(typeof(IVisualTool), toolDesc.Tool.GetType())) continue;
                    IVisualTool tool = (IVisualTool)toolDesc.Tool;
                    tool.PreRender(g);
                }
                catch (Exception)
                {
                }

            }
        }

        public void PostRender(System.Drawing.Graphics g)
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                try
                {
                    if (!Utility.IsType(typeof(IVisualTool), toolDesc.Tool.GetType())) continue;
                    IVisualTool tool = (IVisualTool)toolDesc.Tool;
                    tool.PostRender(g);
                }
                catch (Exception)
                {


                }
            }
        }




        private ToolStrip _oToolStripMenu;

        /// <summary>
        /// Toolstrip menu to use for the tools
        /// </summary>
        public ToolStrip ToolStripMenu
        {
            set
            {
                _oToolStripMenu = value;
                SetupToolStrip(_oToolStripMenu);
            }
        }



        private ToolStripContainer _oToolStripContainer;

        /// <summary>
        /// Tool strip container into which to place new toolstrip bars if needed.
        /// </summary>
        public ToolStripContainer ToolStripContainer
        {
            set
            {
                _oToolStripContainer = value;
                SetupToolStripContainer(_oToolStripContainer);
            }
        }


        private WeifenLuo.WinFormsUI.Docking.DockPanel _oDockPanel;

        public WeifenLuo.WinFormsUI.Docking.DockPanel DockPanel
        {
            get
            {
                return _oDockPanel;
            }
            set
            {
                _oDockPanel = value;
                SetupDockPanel(_oDockPanel);
            }
        }

        /// <summary>
        /// If a tool is deactivated the tool manager should be notified to perform appropriate actions, 
        /// one could imagine that this leads to a default tool taking over or something like that. Or based on 
        /// modifier key states the same tool could be reactivated ... 
        /// </summary>
        /// <param name="oTool">a tool / plugin hitherto active</param>
        public void NotifyDeactictivateTool(ITool oTool)
        {
            // deactivate all tools
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (!(toolDesc.Tool is INonVisualTool)) continue;
                INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                if (tool == oTool) continue;
                if (tool.IsActive) tool.KeepDeactive();
            }

            if (!(oTool is INonVisualTool)) return;
            if (MainForm.ModifierKeys != Keys.Shift)
            {
                INonVisualTool currentTool = (INonVisualTool)oTool;
                currentTool.KeepActive();
            }

        }

        /// <summary>
        /// If a tool is activated, the tool manager has to deactivate other tools.
        /// </summary>
        /// <param name="oTool">the tool to be active</param>
        public void NotifyActivateTool(ITool oTool)
        {
            // deactivate all tools
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (!(toolDesc.Tool is INonVisualTool)) continue;
                INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                if (tool == oTool) continue;
                if (tool.IsActive) tool.KeepDeactive();
            }

        }
        public void DeactivateTools()
        {
            foreach (ToolDescription toolDesc in _oTools.Values)
            {
                if (!(toolDesc.Tool is INonVisualTool)) continue;
                INonVisualTool tool = (INonVisualTool)toolDesc.Tool;
                if (tool.IsActive) tool.KeepDeactive();
            }

            // disable all items here 
            if (_oToolStripMenu != null)
            {
                foreach (ToolStripItem  item in _oToolStripMenu.Items)
                {
                    if (item is ToolStripButton)
                    {
                        ToolStripButton toolStripButton = (ToolStripButton)item;
                        toolStripButton.Checked = false;
                    }
                }
            }
        }

    }
}
